package oplogd

import (
	"time"

	mgo "github.com/globalsign/mgo"
	"github.com/globalsign/mgo/bson"
	"github.com/pkg/errors"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/common"
	coplogd "gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/oplogd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/repo/mgorepo/baser"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
)

// @collname 操作日志集合(i_oplog)
type collOplog struct {
	OplogID    string      `bson:"_id,omitempty"`        //日志唯一编号
	Module     string      `bson:"module,omitempty"`     //模块
	UID        string      `bson:"uid,omitempty"`        //用户编号
	Action     string      `bson:"action,omitempty"`     //操作接口动作
	Desc       string      `bson:"desc,omitempty"`       //描述
	URL        string      `bson:"url,omitempty"`        //URL
	OpTime     time.Time   `bson:"opTime,omitempty"`     //操作时间
	UseTime    int64       `bson:"useTime,omitempty"`    //用时，单位毫秒
	IP         string      `bson:"ip,omitempty"`         //ip
	Agent      string      `bson:"agent,omitempty"`      //浏览器代理
	Refer      string      `bson:"refer,omitempty"`      //refer 引用至
	HTTPStatus int         `bson:"httpStatus,omitempty"` //http状态码
	Status     int         `bson:"status,omitempty"`     //业务状态
	Input      interface{} `bson:"input,omitempty"`      //输入数据（仅记录最多4096字节）
	Output     interface{} `bson:"output,omitempty"`     //输出数据（仅记录最多4096字节）
	Err        string      `bson:"err,omitempty"`        //错误信息
}

func (c collOplog) CollID() string {
	return c.OplogID
}
func (collOplog) CollName() string {
	return collNameOplog
}

func (c *collOplog) FullDesc(e *coplogd.OpLogEntity) {
	c.OplogID = e.ID
	c.Module = e.Module
	c.Desc = e.Desc
	c.UID = e.UID
	c.Action = e.Action
	c.URL = e.URL
	c.OpTime = e.OpTime
	c.UseTime = e.UseTime
	c.IP = e.IP
	c.Agent = e.Agent
	c.Refer = e.Refer
	c.HTTPStatus = e.HTTPStatus
	c.Status = e.Status
	c.Input = e.Input
	c.Output = e.Output
	c.Err = e.Err

}
func (c collOplog) ToDesc() coplogd.OpLogEntity {
	return coplogd.OpLogEntity{
		ID:         c.OplogID,
		Module:     c.Module,
		UID:        c.UID,
		Action:     c.Action,
		Desc:       c.Desc,
		URL:        c.URL,
		OpTime:     c.OpTime,
		UseTime:    c.UseTime,
		IP:         c.IP,
		Agent:      c.Agent,
		Refer:      c.Refer,
		HTTPStatus: c.HTTPStatus,
		Status:     c.Status,
		Input:      c.Input,
		Output:     c.Output,
		Err:        c.Err,
	}
}
func (c collOplog) ToOpLogAggregate() *coplogd.OpLogAggregate {
	return &coplogd.OpLogAggregate{
		OpLogEntity: c.ToDesc(),
	}
}
func (c collOplog) ToAggregate() ddd.Aggregate {
	return c.ToOpLogAggregate()
}

type oplogRepo struct {
	baser.BaseRepo
}

func (r oplogRepo) GetOpLog(ctx ddd.Context, id string) *coplogd.OpLogAggregate {
	co := &collOplog{
		OplogID: id,
	}
	if err := r.DBGetOne(ctx, co); err != nil {
		return nil
	}
	return co.ToOpLogAggregate()
}

// 新增操作日志
// id 返回信息操作日志的唯一标识
func (r oplogRepo) AddOpLog(ctx ddd.Context, oplog *coplogd.OpLogEntity) (err error) {
	co := &collOplog{}
	co.FullDesc(oplog)
	co.OplogID = bson.NewObjectId().Hex()
	return r.DBInsert(ctx, co)
}

// 分页获取操作日志信息列表：根据唯一标识获取下一页指定数量的操作日志信息实体集合
// total 总数量
func (r oplogRepo) QueryPage(ctx ddd.Context, is coplogd.OpLogSearch, pi common.PageInfo) (npi common.PageResult, result []coplogd.OpLogAggregate, err error) {
	query := bson.M{}
	op := bson.M{}
	if is.EndTime != "" {
		if end, err := time.Parse("2006-01-02T15:04:05Z07:00", is.EndTime); err == nil {

			op = bson.M{"$lt": end}
		}
	}
	if is.StartTime != "" {
		if end, err := time.Parse("2006-01-02T15:04:05Z07:00", is.StartTime); err == nil {
			op = bson.M{"$gte": end}
		}
	}
	if len(op) > 0 {
		query["optime"] = op
	}
	if is.UID != "" {
		query["uid"] = is.UID
	}

	var cs []collOplog
	npi, err = r.DBQueryPage(ctx, collNameOplog, pi, "_id", query, nil, nil, &result)
	if err != nil {
		if err == mgo.ErrNotFound {
			err = nil
			npi.End = 1
			return
		}
		err = errors.Wrapf(err, "获取操作历史列表失败.查询条件:%v 分页信息：%v", is, pi)
		return
	}
	if len(cs) == 0 {
		npi.End = 1
		return
	}
	for _, c := range cs {
		a := c.ToOpLogAggregate()
		a.Init(a, r.AggregateRoot(), c.OplogID)
		result = append(result, *a)
	}

	return
}
